This is an R Markdown Notebook. When you execute code within the notebook, the results appear beneath the code.
Try executing this chunk by clicking the Run button within the chunk or by placing your cursor inside it and pressing Ctrl+Shift+Enter. # Tue Jun 7 19:35:18 2022 ——————————
source("tianfengRwrappers.R")
Warning in max(merge_expr$expr) : max里所有的参数都不存在;回覆-Inf
rat Frontier GSE174098 carotid
rat10x <- CreateSeuratObject(Read10X("./rat_scRNAseq/"), names.field = 2, names.delim = "-",
project = "rat", min.cells = 10, min.features = 300) %>%
PercentageFeatureSet(pattern = "^Mt-", col.name = "percent.mt")
table(rat10x$orig.ident)
VlnPlot(rat10x,"nCount_RNA") /
VlnPlot(rat10x,"percent.mt") /
VlnPlot(rat10x, "nFeature_RNA")
rat10x <- rat10x %>% subset(subset = nFeature_RNA > 400 & nFeature_RNA < 4000 &
nCount_RNA > 1000 & nCount_RNA < 30000 & percent.mt< 10) %>%
SCTransform(vars.to.regress = "percent.mt", verbose = F) %>%
RunPCA() %>% FindNeighbors(dims = 1:20) %>%
RunUMAP(dims = 1:20) %>%
FindClusters(resolution = 0.1)

mouse10x <- CreateSeuratObject(Read10X("./celldiscovery_mouse_10x/1/"), names.field = 2, names.delim = "-",
project = "mouse1", min.cells = 10, min.features = 300) %>%
PercentageFeatureSet(pattern = "^mt-", col.name = "percent.mt")
mouse10x2 <- CreateSeuratObject(Read10X("./celldiscovery_mouse_10x/2/"), names.field = 2, names.delim = "-",
project = "mouse2", min.cells = 10, min.features = 300) %>%
PercentageFeatureSet(pattern = "^mt-", col.name = "percent.mt")
mouse10x <- merge(mouse10x,mouse10x2)
VlnPlot(mouse10x,"nCount_RNA") /
VlnPlot(mouse10x,"percent.mt") /
VlnPlot(mouse10x, "nFeature_RNA")
mouse10x <- mouse10x %>% subset(subset = nFeature_RNA > 500 & nFeature_RNA < 5000 &
nCount_RNA > 1000 & nCount_RNA < 30000 & percent.mt < 10) %>%
SCTransform(vars.to.regress = "percent.mt", verbose = F) %>%
RunPCA() %>% FindNeighbors(dims = 1:20) %>%
RunUMAP(dims = 1:20) %>%
FindClusters(resolution = 0.1)
# table(mouse10x$orig.ident)
umapplot(mouse10x)
f("Lmo2",mouse10x)

mouse coronary GSE131778
mouse_coronary_countmatrix <- read.csv("./GSE131776_mouse_scRNAseq.txt", sep = "\t")
func <- function(s) {
paste0(strsplit(s, ".", fixed = T)[[1]][2], "_", strsplit(s, ".", fixed = T)[[1]][1])
}
colnames(mouse_coronary_countmatrix) <- lapply(colnames(mouse_coronary_countmatrix), func) # 拆分样本
mousecor <- CreateSeuratObject(counts = mouse_coronary_countmatrix,
project = "mouse_cor", min.cells = 10, min.features = 300) %>% PercentageFeatureSet(pattern = "^mt-", col.name = "percent.mt")
# saveRDS(mousecor,"mousecor.rds")
table(mousecor$orig.ident)
VlnPlot(mousecor,"nCount_RNA") /
VlnPlot(mousecor,"percent.mt") /
VlnPlot(mousecor, "nFeature_RNA")
mousecor <- mousecor %>% subset(subset = nFeature_RNA > 400 & nFeature_RNA < 4000 &
nCount_RNA > 1000 & nCount_RNA < 30000 & percent.mt < 10) %>%
SCTransform(vars.to.regress = "percent.mt", verbose = F) %>%
RunPCA() %>% FindNeighbors(dims = 1:20) %>%
RunUMAP(dims = 1:20) %>%
FindClusters(resolution = 0.1)
table(mousecor$orig.ident)
saveRDS(mousecor,"mousecor.rds")
SMC2
mousecor <- readRDS("mousecor.rds")
f("Prdm16",mousecor, label.size = 7) + theme(legend.text = element_text(size = 20))

mouse carotid scRNAseq GSE155513
dataload
count_mats <- list.files("./GSE155513_RAW/")
count_mats <- count_mats[count_mats != "sampleinfo.txt"]
allList <- lapply(count_mats, function(file) {
dd <- read.table(paste0("./GSE155513_RAW/", file), row.names = 1,stringsAsFactors = F)
colnames(dd) <- as.character(dd['gene',])
dd <- dd[-1,]
CreateSeuratObject(
counts = dd,
project = file, min.cells = 10, min.features = 300
)
})
# 合并seurat对象
mouse_carotid <- merge(allList[[1]],
y = allList[-1], add.cell.ids = count_mats,
project = "mouse_carotid"
)
rm(allList)
# saveRDS(mouse_carotid,"mouse_carotid.rds")
# View(mouse_carotid)
process
SMC
mouse_carotid <- readRDS("mouse_carotid.rds")
umapplot(mouse_carotid)
umapplot(mouse_carotid,group.by = "orig.ident",label = F)
f("Prdm16",mouse_carotid) #SMC
f("Ly6a",mouse_carotid) #SEM-like cells
multi_featureplot(c("Bmp2","Bmp4","Bmp6"),mouse_carotid)
## BMP4 在这里EC的*大部分*中表达,而在人类样本中BMP4+ EC细胞是少数的
markers <- FindAllMarkers(mouse_carotid,logfc.threshold = 0.5,min.diff.pct = 0.2, only.pos = T)
stromal cells
mouse_carotid_stromal <- subset(mouse_carotid,idents = c(0,2,1,7))
mouse_carotid_stromal <- mouse_carotid_stromal %>% RunPCA() %>% FindNeighbors(dims = 1:20) %>%
RunUMAP(dims = 1:20) %>% FindClusters(resolution = 0.1)
mouse_carotid_stromal <- mouse_carotid_stromal %>% FindClusters(resolution = 0.2)
mouse_carotid_stromal <- readRDS("mouse_carotid_stromal.rds")
# saveRDS(mouse_carotid_stromal,"mouse_carotid_stromal.rds")
umapplot(mouse_carotid_stromal)
f("Dlx2",mouse_carotid_stromal) #Dlx2,Dlx5,Dlx6共同定位
mouse_carotid_stromal <- AddModuleScore(mouse_carotid_stromal, list(mmSMC2_marker), name = "SMC2_score")
f("SMC2_score1", mouse_carotid_stromal,min.cutoff = 0)
multi_featureplot(mmSMC2_marker[1:9],mouse_carotid_stromal,labels = NA, label = F)
分群表
table(group_tab[Dlx5poscells])/table(group_tab)
GSM4705592_RPS003_matrix.txt.gz GSM4705593_RPS004_matrix.txt.gz GSM4705594_RPS011_matrix.txt.gz GSM4705595_RPS012_matrix.txt.gz GSM4705596_RPS007_matrix.txt.gz
0.080645161 0.076949502 0.130000000 0.029882604 0.058282209
GSM4705597_RPS008_matrix.txt.gz GSM4705598_RPS001_matrix.txt.gz GSM4705599_RPS002_matrix.txt.gz GSM4705600_RPS017_matrix.txt.gz GSM4705601_RPS018_matrix.txt.gz
0.004746835 0.039230575 0.003976143 0.093492209 0.095634096
GSM4705602_RPS013_matrix.txt.gz GSM4705603_RPS014_matrix.txt.gz GSM4705604_RPS015_matrix.txt.gz GSM4705605_RPS016_matrix.txt.gz
0.066773504 0.019255456 0.042503503 0.030303030
图
ggsave("./fig7_mouse/cir_mouse_carotid_stromal2.png" ,plot = p, height = 12, width = 16,device = png)
Warning: Removed 1 rows containing missing values (geom_text).
human ds2
p <- multi_featureplot(c("FRZB","SOST","DLX5","DLX6"), ds2, labels = NA, label.size = 6)
ggsave("refds2_SMC2_carotid_stromal.png",plot = p, height = 7, width = 7,device = png)
Warning: Removed 1 rows containing missing values (geom_text).
human bulk RNA-seq GSE120521 carotid stable/unstable FPKM
fpkm2tpm <- function(fpkm){
exp(log(fpkm) - log(sum(fpkm)) + log(1e6))
}
fpkm_matrix <- read.csv("GSE120521_FPKM.csv")
# fpkm_matrix <- distinct(fpkm_matrix) #去除重复行
fpkm_matrix <- fpkm_matrix[!duplicated(fpkm_matrix$name),]
rownames(fpkm_matrix) <- fpkm_matrix$name
fpkm_matrix$name <- NULL
tpm_matrix <- apply(fpkm_matrix, 2, fpkm2tpm)
colSums(tpm_matrix)
group_file <- c("stable","unstable","stable","unstable",
"stable","unstable","stable","unstable")
boxplot(tpm_matrix, las = 2)
expr_mat <- tpm_matrix[!apply(tpm_matrix, 1, function(x){sum(floor(x) == 0)>3}),]
boxplot(expr_mat, las = 2)
library(limma)
expr_mat <- normalizeBetweenArrays(expr_mat)
expr_mat <- log2(expr_mat+1) #使用log2 scale
#PCA
library(ggfortify)
df <- as.data.frame(t(expr_mat))
df$group <- group_file
autoplot(prcomp(df[,1:(ncol(df)-1)]), data=df, colour = 'group')+ theme_bw()
# If the sequencing depth is reasonably consistent across the RNA samples, then the simplest and most robust approach to differential exis to use limma-trend.
fit <- lmFit(expr_mat, group_file)
fit <- treat(fit, lfc=log2(1.2), trend=TRUE)
topTreat(fit, coef=ncol(design))
library(ggpubr)
dat <- expr_mat
design <- model.matrix(~factor(group_file))
fit <- lmFit(dat, design)
fit <- eBayes(fit)
# options(digits = 4)
topTable(fit,coef=2,adjust='BH')
deg <- topTable(fit,coef=2,adjust='BH',number = Inf)
head(deg)
write.csv(deg,"./datatable/stable vs unstable.csv")
## look up FRZB, SOST, PRDM6, OGN
ds1markers[ds1markers$cluster == "SMC2",]$gene
ds2markers[ds2markers$cluster == "SMC3",]$gene
smc2markers <- intersect(ds1markers[ds1markers$cluster == "SMC2",]$gene, ds2markers[ds2markers$cluster == "SMC3",]$gene)
deg[intersect(smc2markers, rownames(deg)),]
ds1markers[ds1markers$cluster == "SMC1",]$gene
ds2markers[ds2markers$cluster == "SMC1",]$gene
SMC1markers <- intersect(ds1markers[ds1markers$cluster == "SMC1",]$gene, ds2markers[ds2markers$cluster == "SMC1",]$gene)
deg[intersect(SMC1markers, rownames(deg)),]

Add a new chunk by clicking the Insert Chunk button on the toolbar or by pressing Ctrl+Alt+I.
When you save the notebook, an HTML file containing the code and output will be saved alongside it (click the Preview button or press Ctrl+Shift+K to preview the HTML file).
The preview shows you a rendered HTML copy of the contents of the editor. Consequently, unlike Knit, Preview does not run any R code chunks. Instead, the output of the chunk when it was last run in the editor is displayed.
LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKVGhpcyBpcyBhbiBbUiBNYXJrZG93bl0oaHR0cDovL3JtYXJrZG93bi5yc3R1ZGlvLmNvbSkgTm90ZWJvb2suIFdoZW4geW91IGV4ZWN1dGUgY29kZSB3aXRoaW4gdGhlIG5vdGVib29rLCB0aGUgcmVzdWx0cyBhcHBlYXIgYmVuZWF0aCB0aGUgY29kZS4gCgpUcnkgZXhlY3V0aW5nIHRoaXMgY2h1bmsgYnkgY2xpY2tpbmcgdGhlICpSdW4qIGJ1dHRvbiB3aXRoaW4gdGhlIGNodW5rIG9yIGJ5IHBsYWNpbmcgeW91ciBjdXJzb3IgaW5zaWRlIGl0IGFuZCBwcmVzc2luZyAqQ3RybCtTaGlmdCtFbnRlciouIAojIFR1ZSBKdW4gIDcgMTk6MzU6MTggMjAyMiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCgpgYGB7cn0Kc291cmNlKCJ0aWFuZmVuZ1J3cmFwcGVycy5SIikKYGBgCgojIHJhdCBGcm9udGllciAqR1NFMTc0MDk4KiBjYXJvdGlkCmBgYHtyIGZpZy53aWR0aD00LCBmaWcuaGVpZ2h0PTh9CnJhdDEweCA8LSBDcmVhdGVTZXVyYXRPYmplY3QoUmVhZDEwWCgiLi9yYXRfc2NSTkFzZXEvIiksIG5hbWVzLmZpZWxkID0gMiwgbmFtZXMuZGVsaW0gPSAiLSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvamVjdCA9ICJyYXQiLCBtaW4uY2VsbHMgPSAxMCwgbWluLmZlYXR1cmVzID0gMzAwKSAlPiUKICBQZXJjZW50YWdlRmVhdHVyZVNldChwYXR0ZXJuID0gIl5NdC0iLCBjb2wubmFtZSA9ICJwZXJjZW50Lm10IikgCgp0YWJsZShyYXQxMHgkb3JpZy5pZGVudCkKVmxuUGxvdChyYXQxMHgsIm5Db3VudF9STkEiKSAvClZsblBsb3QocmF0MTB4LCJwZXJjZW50Lm10IikgLwpWbG5QbG90KHJhdDEweCwgIm5GZWF0dXJlX1JOQSIpCgoKcmF0MTB4IDwtIHJhdDEweCAlPiUgc3Vic2V0KHN1YnNldCA9IG5GZWF0dXJlX1JOQSA+IDQwMCAmIG5GZWF0dXJlX1JOQSA8IDQwMDAgJgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuQ291bnRfUk5BID4gMTAwMCAmICBuQ291bnRfUk5BIDwgMzAwMDAgJiBwZXJjZW50Lm10PCAxMCkgJT4lCiAgICBTQ1RyYW5zZm9ybSh2YXJzLnRvLnJlZ3Jlc3MgPSAicGVyY2VudC5tdCIsIHZlcmJvc2UgPSBGKSAlPiUgCiAgICBSdW5QQ0EoKSAlPiUgRmluZE5laWdoYm9ycyhkaW1zID0gMToyMCkgJT4lIAogICAgUnVuVU1BUChkaW1zID0gMToyMCkgJT4lIAogICAgRmluZENsdXN0ZXJzKHJlc29sdXRpb24gPSAwLjEpCgpgYGAKCgpgYGB7ciBmaWcud2lkdGg9NCwgZmlnLmhlaWdodD0zfQp1bWFwcGxvdChyYXQxMHgpCm11bHRpX2ZlYXR1cmVwbG90KGMoIkFjdGEyIiwiQ25uMSIsIkZuMSIsIkx1bSIsIlZjYW0xIiwiTHk2YSIsIkRseDUiLCJEbHg2IiwiU29zdCIpLCByYXQxMHgpCgoKZigiQm1wcjFiIiwgcmF0MTB4KSAvCmYoIkJtcHIxYSIsIHJhdDEweCkKdGFibGUocmF0MTB4JHNldXJhdF9jbHVzdGVycykKCnJhdDEweDAgPC0gc3Vic2V0KHJhdDEweCxpZGVudCA9IDApCgpmKCJTb3N0IixyYXQxMHgpCm5jb2woc3Vic2V0KHJhdDEweDAsIHN1YnNldCA9IEJtcHIxYSA+IDApKQpuY29sKHN1YnNldChyYXQxMHgwLCBzdWJzZXQgPSBCbXByMWIgPiAwKSkKbmNvbChzdWJzZXQocmF0MTB4MCwgc3Vic2V0ID0gQm1wcjFhID4gMCAmIEJtcHIxYiA+IDApKQoKbmNvbChzdWJzZXQocmF0MTB4MCwgc3Vic2V0ID0gU29zdCA+IDAgJiBCbXByMWIgPiAwKSkKbmNvbChzdWJzZXQocmF0MTB4MCwgc3Vic2V0ID0gU29zdCA+IDAgJiBCbXByMWEgPiAwKSkKCm5jb2wocmF0MTB4MCkKYGBgCgoKYGBge3J9Cm1vdXNlMTB4IDwtIENyZWF0ZVNldXJhdE9iamVjdChSZWFkMTBYKCIuL2NlbGxkaXNjb3ZlcnlfbW91c2VfMTB4LzEvIiksIG5hbWVzLmZpZWxkID0gMiwgbmFtZXMuZGVsaW0gPSAiLSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvamVjdCA9ICJtb3VzZTEiLCBtaW4uY2VsbHMgPSAxMCwgbWluLmZlYXR1cmVzID0gMzAwKSAlPiUKICBQZXJjZW50YWdlRmVhdHVyZVNldChwYXR0ZXJuID0gIl5tdC0iLCBjb2wubmFtZSA9ICJwZXJjZW50Lm10IikgCgptb3VzZTEweDIgPC0gQ3JlYXRlU2V1cmF0T2JqZWN0KFJlYWQxMFgoIi4vY2VsbGRpc2NvdmVyeV9tb3VzZV8xMHgvMi8iKSwgbmFtZXMuZmllbGQgPSAyLCBuYW1lcy5kZWxpbSA9ICItIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9qZWN0ID0gIm1vdXNlMiIsIG1pbi5jZWxscyA9IDEwLCBtaW4uZmVhdHVyZXMgPSAzMDApICU+JQogIFBlcmNlbnRhZ2VGZWF0dXJlU2V0KHBhdHRlcm4gPSAiXm10LSIsIGNvbC5uYW1lID0gInBlcmNlbnQubXQiKSAKCm1vdXNlMTB4IDwtIG1lcmdlKG1vdXNlMTB4LG1vdXNlMTB4MikKClZsblBsb3QobW91c2UxMHgsIm5Db3VudF9STkEiKSAvClZsblBsb3QobW91c2UxMHgsInBlcmNlbnQubXQiKSAvClZsblBsb3QobW91c2UxMHgsICJuRmVhdHVyZV9STkEiKQoKbW91c2UxMHggPC0gbW91c2UxMHggJT4lIHN1YnNldChzdWJzZXQgPSBuRmVhdHVyZV9STkEgPiA1MDAgJiBuRmVhdHVyZV9STkEgPCA1MDAwICYKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbkNvdW50X1JOQSA+IDEwMDAgJiAgbkNvdW50X1JOQSA8IDMwMDAwICYgcGVyY2VudC5tdCA8IDEwKSAlPiUKICAgIFNDVHJhbnNmb3JtKHZhcnMudG8ucmVncmVzcyA9ICJwZXJjZW50Lm10IiwgdmVyYm9zZSA9IEYpICU+JSAKICAgIFJ1blBDQSgpICU+JSBGaW5kTmVpZ2hib3JzKGRpbXMgPSAxOjIwKSAlPiUgCiAgICBSdW5VTUFQKGRpbXMgPSAxOjIwKSAlPiUgCiAgICBGaW5kQ2x1c3RlcnMocmVzb2x1dGlvbiA9IDAuMSkKIyB0YWJsZShtb3VzZTEweCRvcmlnLmlkZW50KQoKCnVtYXBwbG90KG1vdXNlMTB4KQpmKCJMbW8yIixtb3VzZTEweCkKYGBgCgoKYGBge3J9ClNNQzJfbWFya2VyIDwtIGFzLmNoYXJhY3RlcihyZWFkLnRhYmxlKCJTTUMyIikkVjEpCmxpYnJhcnkoaG9tb2xvZ2VuZSkKCm1tU01DMl9tYXJrZXIgPC0gaG9tb2xvZ2VuZShTTUMyX21hcmtlciwgaW5UYXggPSA5NjA2LCBvdXRUYXggPSAxMDA5MCkKbW1TTUMyX21hcmtlciA8LSBtbVNNQzJfbWFya2VyJGAxMDA5MGAKbW1TTUMyX21hcmtlciA8LSBpbnRlcnNlY3Qocm93bmFtZXMobW91c2UxMHgpLCBtbVNNQzJfbWFya2VyKQptb3VzZTEweCA8LSBBZGRNb2R1bGVTY29yZShtb3VzZTEweCwgbGlzdChtbVNNQzJfbWFya2VyKSwgbmFtZSA9ICJTTUMyX3Njb3JlIikKZigiU01DMl9zY29yZTEiLG1vdXNlMTB4LCBtaW4uY3V0b2ZmID0gMCkKRG90cGxvdCgiU01DMl9zY29yZTEiLG1vdXNlMTB4KQpgYGAKCgojIG1vdXNlIGNvcm9uYXJ5ICpHU0UxMzE3NzgqCmBgYHtyfQptb3VzZV9jb3JvbmFyeV9jb3VudG1hdHJpeCA8LSByZWFkLmNzdigiLi9HU0UxMzE3NzZfbW91c2Vfc2NSTkFzZXEudHh0Iiwgc2VwID0gIlx0IikKZnVuYyA8LSBmdW5jdGlvbihzKSB7CiAgcGFzdGUwKHN0cnNwbGl0KHMsICIuIiwgZml4ZWQgPSBUKVtbMV1dWzJdLCAiXyIsIHN0cnNwbGl0KHMsICIuIiwgZml4ZWQgPSBUKVtbMV1dWzFdKQp9CmNvbG5hbWVzKG1vdXNlX2Nvcm9uYXJ5X2NvdW50bWF0cml4KSA8LSBsYXBwbHkoY29sbmFtZXMobW91c2VfY29yb25hcnlfY291bnRtYXRyaXgpLCBmdW5jKSAjIOaLhuWIhuagt+acrApgYGAKCmBgYHtyIGZpZy53aWR0aD0gNCwgZmlnLmhlaWdodD04fQptb3VzZWNvciA8LSBDcmVhdGVTZXVyYXRPYmplY3QoY291bnRzID0gbW91c2VfY29yb25hcnlfY291bnRtYXRyaXgsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvamVjdCA9ICJtb3VzZV9jb3IiLCBtaW4uY2VsbHMgPSAxMCwgbWluLmZlYXR1cmVzID0gMzAwKSAlPiUgIFBlcmNlbnRhZ2VGZWF0dXJlU2V0KHBhdHRlcm4gPSAiXm10LSIsIGNvbC5uYW1lID0gInBlcmNlbnQubXQiKSAKCiMgc2F2ZVJEUyhtb3VzZWNvciwibW91c2Vjb3IucmRzIikKdGFibGUobW91c2Vjb3Ikb3JpZy5pZGVudCkKVmxuUGxvdChtb3VzZWNvciwibkNvdW50X1JOQSIpIC8KVmxuUGxvdChtb3VzZWNvciwicGVyY2VudC5tdCIpIC8KVmxuUGxvdChtb3VzZWNvciwgIm5GZWF0dXJlX1JOQSIpCgoKbW91c2Vjb3IgPC0gbW91c2Vjb3IgJT4lIHN1YnNldChzdWJzZXQgPSBuRmVhdHVyZV9STkEgPiA0MDAgJiBuRmVhdHVyZV9STkEgPCA0MDAwICYKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbkNvdW50X1JOQSA+IDEwMDAgJiAgbkNvdW50X1JOQSA8IDMwMDAwICYgcGVyY2VudC5tdCA8IDEwKSAlPiUKICAgIFNDVHJhbnNmb3JtKHZhcnMudG8ucmVncmVzcyA9ICJwZXJjZW50Lm10IiwgdmVyYm9zZSA9IEYpICU+JSAKICAgIFJ1blBDQSgpICU+JSBGaW5kTmVpZ2hib3JzKGRpbXMgPSAxOjIwKSAlPiUgCiAgICBSdW5VTUFQKGRpbXMgPSAxOjIwKSAlPiUgCiAgICBGaW5kQ2x1c3RlcnMocmVzb2x1dGlvbiA9IDAuMSkKdGFibGUobW91c2Vjb3Ikb3JpZy5pZGVudCkKc2F2ZVJEUyhtb3VzZWNvciwibW91c2Vjb3IucmRzIikKYGBgCgojIyMgU01DMgpgYGB7ciBmaWcud2lkdGg9NCwgZmlnLmhlaWdodD0zfQptb3VzZWNvciA8LSByZWFkUkRTKCJtb3VzZWNvci5yZHMiKQpmKCJQcmRtMTYiLG1vdXNlY29yLCBsYWJlbC5zaXplID0gNykgKyB0aGVtZShsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMjApKQoKYGBgCgoKYGBge3IgZmlnLndpZHRoPTQsIGZpZy5oZWlnaHQ9M30KbW91c2Vjb3Jfc3Ryb21hbCA8LSBzdWJzZXQobW91c2Vjb3IsaWRlbnRzID0gYygwLDEsMikpCgptb3VzZWNvcl9zdHJvbWFsIDwtIG1vdXNlY29yX3N0cm9tYWwgJT4lIFJ1blBDQSgpICU+JSBGaW5kTmVpZ2hib3JzKGRpbXMgPSAxOjIwKSAlPiUgCiAgICBSdW5VTUFQKGRpbXMgPSAxOjIwKSAlPiUgRmluZENsdXN0ZXJzKHJlc29sdXRpb24gPSAwLjIpCm1vdXNlY29yX3N0cm9tYWwgPC0gbW91c2Vjb3Jfc3Ryb21hbCAlPiUgRmluZENsdXN0ZXJzKHJlc29sdXRpb24gPSAwLjIpCgoKbW91c2Vjb3Jfc3Ryb21hbCA8LSByZWFkUkRTKCJtb3VzZWNvcl9zdHJvbWFsLnJkcyIpCgp1bWFwcGxvdChtb3VzZWNvcl9zdHJvbWFsLCBsYWJlbC5zaXplID0gNikgKyB0aGVtZShsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMjApKQptdWx0aV9mZWF0dXJlcGxvdChjKCJBY3RhMiIsIkNubjEiLCJGbjEiLCJMdW0iLCJWY2FtMSIsIkx5NmEiLCJEbHg1IiwiRGx4NiIpLCBtb3VzZWNvcl9zdHJvbWFsLGxhYmVscyA9IE5BKQoKCmxldmVscyhJZGVudHMobW91c2Vjb3Jfc3Ryb21hbCkpIDwtIGMoIlNNQzEiLCJGaWJyb2JsYXN0MSIsIkZpYnJvbXlvY3l0ZSIsIlNNQzEiLCJGaWJyb2JsYXN0MiIsIlNNQzIiKQpmKCJBY3RhMiIsbW91c2Vjb3Jfc3Ryb21hbCxsYWJlbC5zaXplID0gNikKcCA8LSBtdWx0aV9mZWF0dXJlcGxvdChjKCJBY3RhMiIsIkNubjEiLCJGbjEiLCJMdW0iLCJWY2FtMSIsIkx5NmEiLCJEbHg1IiwiRGx4NiIsIkxnYWxzMyIpLG1vdXNlY29yX3N0cm9tYWwsbGFiZWxzID0gTkEsbGFiZWwuc2l6ZSA9IDYpCmdnc2F2ZSgibmF0bWVkX21vdXNlX2Nvcm9uYXJ5X3N0cm9tYWwyLnBuZyIscGxvdCA9IHAsIGhlaWdodCA9IDEyLCB3aWR0aCA9IDE2LGRldmljZSA9IHBuZykKdW1hcHBsb3QobW91c2Vjb3Jfc3Ryb21hbCwgbGFiZWwuc2l6ZSA9IDYpICsgdGhlbWUobGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE4KSkKCm1vdXNlY29yX3N0cm9tYWwgPC0gQWRkTW9kdWxlU2NvcmUobW91c2Vjb3Jfc3Ryb21hbCwgbGlzdChtbVNNQzJfbWFya2VyKSwgbmFtZSA9ICJTTUMyX3Njb3JlIikKZigiU01DMl9zY29yZTEiLCBtb3VzZWNvcl9zdHJvbWFsLG1pbi5jdXRvZmYgPSAwKQoKYGBgCgojIG1vdXNlIGNhcm90aWQgc2NSTkFzZXEgKkdTRTE1NTUxMyoKIyMjIGRhdGFsb2FkCmBgYHtyfQpjb3VudF9tYXRzIDwtIGxpc3QuZmlsZXMoIi4vR1NFMTU1NTEzX1JBVy8iKQpjb3VudF9tYXRzIDwtIGNvdW50X21hdHNbY291bnRfbWF0cyAhPSAic2FtcGxlaW5mby50eHQiXQphbGxMaXN0IDwtIGxhcHBseShjb3VudF9tYXRzLCBmdW5jdGlvbihmaWxlKSB7CiAgZGQgPC0gcmVhZC50YWJsZShwYXN0ZTAoIi4vR1NFMTU1NTEzX1JBVy8iLCBmaWxlKSwgcm93Lm5hbWVzID0gMSxzdHJpbmdzQXNGYWN0b3JzID0gRikKICBjb2xuYW1lcyhkZCkgPC0gYXMuY2hhcmFjdGVyKGRkWydnZW5lJyxdKQogIGRkIDwtIGRkWy0xLF0KICBDcmVhdGVTZXVyYXRPYmplY3QoCiAgICBjb3VudHMgPSBkZCwKICAgIHByb2plY3QgPSBmaWxlLCBtaW4uY2VsbHMgPSAxMCwgbWluLmZlYXR1cmVzID0gMzAwCiAgKQp9KQojIOWQiOW5tnNldXJhdOWvueixoQptb3VzZV9jYXJvdGlkIDwtIG1lcmdlKGFsbExpc3RbWzFdXSwgCiAgeSA9IGFsbExpc3RbLTFdLCBhZGQuY2VsbC5pZHMgPSBjb3VudF9tYXRzLAogIHByb2plY3QgPSAibW91c2VfY2Fyb3RpZCIKKQpybShhbGxMaXN0KQoKIyBzYXZlUkRTKG1vdXNlX2Nhcm90aWQsIm1vdXNlX2Nhcm90aWQucmRzIikKIyBWaWV3KG1vdXNlX2Nhcm90aWQpCmBgYAoKIyMjIHByb2Nlc3MKYGBge3J9Cm1vdXNlX2Nhcm90aWQgPC0gcmVhZFJEUygibW91c2VfY2Fyb3RpZC5yZHMiKQoKbW91c2VfY2Fyb3RpZCA8LSBtb3VzZV9jYXJvdGlkICU+JSAgUGVyY2VudGFnZUZlYXR1cmVTZXQocGF0dGVybiA9ICJebXQtIiwgY29sLm5hbWUgPSAicGVyY2VudC5tdCIpICU+JQpzdWJzZXQoc3Vic2V0ID0gbkZlYXR1cmVfUk5BID4gNTAwICYgbkZlYXR1cmVfUk5BIDwgMzAwMCAmCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5Db3VudF9STkEgPiAxMDAwICYgIG5Db3VudF9STkEgPCAyMDAwMCAmIHBlcmNlbnQubXQgPCAxMCkgJT4lCiAgICBTQ1RyYW5zZm9ybSh2YXJzLnRvLnJlZ3Jlc3MgPSAicGVyY2VudC5tdCIsIHZlcmJvc2UgPSBGKSAlPiUgCiAgICBSdW5QQ0EoKSAlPiUgRmluZE5laWdoYm9ycyhkaW1zID0gMToyMCkgJT4lIAogICAgUnVuVU1BUChkaW1zID0gMToyMCkgJT4lIAogICAgRmluZENsdXN0ZXJzKHJlc29sdXRpb24gPSAwLjEpCgpzYXZlUkRTKG1vdXNlX2Nhcm90aWQsIm1vdXNlX2Nhcm90aWQucmRzIikKYGBgCgojIyMgU01DCmBgYHtyfQptb3VzZV9jYXJvdGlkIDwtIHJlYWRSRFMoIm1vdXNlX2Nhcm90aWQucmRzIikKdW1hcHBsb3QobW91c2VfY2Fyb3RpZCkKdW1hcHBsb3QobW91c2VfY2Fyb3RpZCxncm91cC5ieSA9ICJvcmlnLmlkZW50IixsYWJlbCA9IEYpCmYoIlByZG0xNiIsbW91c2VfY2Fyb3RpZCkgI1NNQwpmKCJMeTZhIixtb3VzZV9jYXJvdGlkKSAjU0VNLWxpa2UgY2VsbHMKCm11bHRpX2ZlYXR1cmVwbG90KGMoIkJtcDIiLCJCbXA0IiwiQm1wNiIpLG1vdXNlX2Nhcm90aWQpCgojIyBCTVA0IOWcqOi/memHjEVD55qEKuWkp+mDqOWIhirkuK3ooajovr7vvIzogIzlnKjkurrnsbvmoLfmnKzkuK1CTVA0KyBFQ+e7huiDnuaYr+WwkeaVsOeahAptYXJrZXJzIDwtIEZpbmRBbGxNYXJrZXJzKG1vdXNlX2Nhcm90aWQsbG9nZmMudGhyZXNob2xkID0gMC41LG1pbi5kaWZmLnBjdCA9IDAuMiwgb25seS5wb3MgPSBUKQoKCmBgYAojIyMgc3Ryb21hbCBjZWxscwpgYGB7ciBmaWcud2lkdGg9NCwgZmlnLmhlaWdodD0zfQptb3VzZV9jYXJvdGlkX3N0cm9tYWwgPC0gc3Vic2V0KG1vdXNlX2Nhcm90aWQsaWRlbnRzID0gYygwLDIsMSw3KSkKbW91c2VfY2Fyb3RpZF9zdHJvbWFsIDwtIG1vdXNlX2Nhcm90aWRfc3Ryb21hbCAlPiUgUnVuUENBKCkgJT4lIEZpbmROZWlnaGJvcnMoZGltcyA9IDE6MjApICU+JSAKICAgIFJ1blVNQVAoZGltcyA9IDE6MjApICU+JSBGaW5kQ2x1c3RlcnMocmVzb2x1dGlvbiA9IDAuMSkKbW91c2VfY2Fyb3RpZF9zdHJvbWFsIDwtIG1vdXNlX2Nhcm90aWRfc3Ryb21hbCAlPiUgRmluZENsdXN0ZXJzKHJlc29sdXRpb24gPSAwLjIpCgptb3VzZV9jYXJvdGlkX3N0cm9tYWwgPC0gcmVhZFJEUygibW91c2VfY2Fyb3RpZF9zdHJvbWFsLnJkcyIpCiMgc2F2ZVJEUyhtb3VzZV9jYXJvdGlkX3N0cm9tYWwsIm1vdXNlX2Nhcm90aWRfc3Ryb21hbC5yZHMiKQoKdW1hcHBsb3QobW91c2VfY2Fyb3RpZF9zdHJvbWFsKQpmKCJEbHgyIixtb3VzZV9jYXJvdGlkX3N0cm9tYWwpICNEbHgyLERseDUsRGx4NuWFseWQjOWumuS9jQoKbW91c2VfY2Fyb3RpZF9zdHJvbWFsIDwtIEFkZE1vZHVsZVNjb3JlKG1vdXNlX2Nhcm90aWRfc3Ryb21hbCwgbGlzdChtbVNNQzJfbWFya2VyKSwgbmFtZSA9ICJTTUMyX3Njb3JlIikKZigiU01DMl9zY29yZTEiLCBtb3VzZV9jYXJvdGlkX3N0cm9tYWwsbWluLmN1dG9mZiA9IDApCgptdWx0aV9mZWF0dXJlcGxvdChtbVNNQzJfbWFya2VyWzE6OV0sbW91c2VfY2Fyb3RpZF9zdHJvbWFsLGxhYmVscyA9IE5BLCBsYWJlbCA9IEYpCmBgYAoKIyMjIyDliIbnvqTooagKYGBge3IgZmlnLndpZHRoPTQsIGZpZy5oZWlnaHQ9M30KRGx4NXBvc2NlbGxzIDwtIFdoaWNoQ2VsbHMobW91c2VfY2Fyb3RpZF9zdHJvbWFsLCBleHByZXNzaW9uID0gYERseDZgID4gMCAmIGBEbHg1YCA+IDApCmdyb3VwX3RhYiA8LSBJZGVudHMobW91c2VfY2Fyb3RpZF9zdHJvbWFsKQp0YWJsZShncm91cF90YWJbRGx4NXBvc2NlbGxzXSkvdGFibGUoZ3JvdXBfdGFiKSAKIyDlnKhjbHVzdGVyNSDmnIk0My44JeeahOe7huiDnuihqOi+vkRMWDXvvIwzOC40JeeahOe7huiDnuihqOi+vkRMWDYsMjAuMiXnmoTnu4bog57ooajovr7kuKTogIUKCiMjIOWFs+S6juagt+acrOS/oeaBrwpEbHg1cG9zY2VsbHMgPC0gV2hpY2hDZWxscyhtb3VzZV9jYXJvdGlkX3N0cm9tYWwsIGlkZW50cyA9ICJETFggU01DIikKZ3JvdXBfdGFiIDwtIG1vdXNlX2Nhcm90aWRfc3Ryb21hbCRvcmlnLmlkZW50CnRhYmxlKGdyb3VwX3RhYltEbHg1cG9zY2VsbHNdKS90YWJsZShncm91cF90YWIpIAp0YWJsZShncm91cF90YWJbRGx4NXBvc2NlbGxzXSkKYGBgCgojIyMjIOWbvgpgYGB7ciBmaWcud2lkdGg9NCwgZmlnLmhlaWdodD0zfQpsZXZlbHMoSWRlbnRzKG1vdXNlX2Nhcm90aWRfc3Ryb21hbCkpIDwtIGMoIlNFTSBjZWxsIiwiRmlicm9ibGFzdDEiLCJTTUMiLCJTTUMiLCJGaWJyb2JsYXN0MiIsIkRMWCBTTUMiLCJVbmFubm90YXRlZCIsIlVuYW5ub3RhdGVkIikKdW1hcHBsb3QobW91c2VfY2Fyb3RpZF9zdHJvbWFsLGxhYmVsLnNpemUgPSA2LGxhYmVsID0gRikgJT4lIGdnc2F2ZSgiLi9maWc3X21vdXNlL2Npcl9tb3VzZV9jYXJvdGlkX3N0cm9tYWx1bWFwMi5wbmciLHBsb3QgPSAuLCBoZWlnaHQgPSA1LCB3aWR0aCA9IDYsZGV2aWNlID0gcG5nKQoKcCA8LSBtdWx0aV9mZWF0dXJlcGxvdChjKCJBY3RhMiIsIkNubjEiLCJGbjEiLCJMdW0iLCJWY2FtMSIsIkx5NmEiLCJEbHg1IiwiRGx4NiIsIkxnYWxzMyIpLG1vdXNlX2Nhcm90aWRfc3Ryb21hbCxsYWJlbHMgPSBOQSwgbGFiZWwuc2l6ZSA9IDYsIGxhYmVsID0gRikKZ2dzYXZlKCIuL2ZpZzdfbW91c2UvY2lyX21vdXNlX2Nhcm90aWRfc3Ryb21hbDIucG5nIiAscGxvdCA9IHAsIGhlaWdodCA9IDEyLCB3aWR0aCA9IDE2LGRldmljZSA9IHBuZykKRG90cGxvdChjKCJBY3RhMiIsIkNubjEiLCJGbjEiLCJMdW0iLCJWY2FtMSIsIkx5NmEiLCJEbHg1IiwiRGx4NiIsIlNvc3QiKSxtb3VzZV9jYXJvdGlkX3N0cm9tYWwpCgpETFhwb3NTTUNfbWFya2VycyA8LSBGaW5kTWFya2Vycyhtb3VzZV9jYXJvdGlkX3N0cm9tYWwsIGlkZW50LjEgPSAiRExYIFNNQyIsIGxvZ2ZjLnRocmVzaG9sZCA9IDAuNCwgb25seS5wb3MgPSBULCBtaW4uZGlmZi5wY3QgPSAwLjIpCmYoIkRseDUiLG1vdXNlX2Nhcm90aWRfc3Ryb21hbCkKCmxpYnJhcnkob3JnLk1tLmVnLmRiKQpHT19kb3RwbG90KHJvd25hbWVzKERMWHBvc1NNQ19tYXJrZXJzKSwgT3JnRGIgPSBvcmcuTW0uZWcuZGIpCmBgYAojIGh1bWFuIGRzMgpgYGB7cn0KcCA8LSBtdWx0aV9mZWF0dXJlcGxvdChjKCJBQ1RBMiIsIkNOTjEiLCJGTjEiLCJMVU0iLCJWQ0FNMSIsIkxZNkEiLCJETFg1IiwiRExYNiIsIkxHQUxTMyIsIlNPU1QiKSwgZHMyLCBsYWJlbHMgPSBOQSwgbGFiZWwuc2l6ZSA9IDYpCgpnZ3NhdmUoInJlZmRzMl9jYXJvdGlkX3N0cm9tYWwucG5nIixwbG90ID0gcCwgaGVpZ2h0ID0gMTIsIHdpZHRoID0gMTIsZGV2aWNlID0gcG5nKQoKCnAgPC0gbXVsdGlfZmVhdHVyZXBsb3QoYygiRlJaQiIsIlNPU1QiLCJETFg1IiwiRExYNiIpLCBkczIsIGxhYmVscyA9IE5BLCBsYWJlbC5zaXplID0gNikKZ2dzYXZlKCJyZWZkczJfU01DMl9jYXJvdGlkX3N0cm9tYWwucG5nIixwbG90ID0gcCwgaGVpZ2h0ID0gNywgd2lkdGggPSA3LGRldmljZSA9IHBuZykKYGBgCgoKIyBodW1hbiBidWxrIFJOQS1zZXEgKkdTRTEyMDUyMSogY2Fyb3RpZCBzdGFibGUvdW5zdGFibGUgRlBLTQpgYGB7cn0KZnBrbTJ0cG0gPC0gZnVuY3Rpb24oZnBrbSl7CiAgZXhwKGxvZyhmcGttKSAtIGxvZyhzdW0oZnBrbSkpICsgbG9nKDFlNikpCn0KCmZwa21fbWF0cml4IDwtIHJlYWQuY3N2KCJHU0UxMjA1MjFfRlBLTS5jc3YiKQojIGZwa21fbWF0cml4IDwtIGRpc3RpbmN0KGZwa21fbWF0cml4KSAj5Y676Zmk6YeN5aSN6KGMCmZwa21fbWF0cml4IDwtIGZwa21fbWF0cml4WyFkdXBsaWNhdGVkKGZwa21fbWF0cml4JG5hbWUpLF0Kcm93bmFtZXMoZnBrbV9tYXRyaXgpIDwtIGZwa21fbWF0cml4JG5hbWUKZnBrbV9tYXRyaXgkbmFtZSA8LSBOVUxMCgp0cG1fbWF0cml4IDwtIGFwcGx5KGZwa21fbWF0cml4LCAyLCBmcGttMnRwbSkKY29sU3Vtcyh0cG1fbWF0cml4KQoKZ3JvdXBfZmlsZSA8LSBjKCJzdGFibGUiLCJ1bnN0YWJsZSIsInN0YWJsZSIsInVuc3RhYmxlIiwKICAgICAgICAgICAgICAgICJzdGFibGUiLCJ1bnN0YWJsZSIsInN0YWJsZSIsInVuc3RhYmxlIikKYm94cGxvdCh0cG1fbWF0cml4LCBsYXMgPSAyKQoKZXhwcl9tYXQgPC0gdHBtX21hdHJpeFshYXBwbHkodHBtX21hdHJpeCwgMSwgZnVuY3Rpb24oeCl7c3VtKGZsb29yKHgpID09IDApPjN9KSxdCgpib3hwbG90KGV4cHJfbWF0LCBsYXMgPSAyKQoKbGlicmFyeShsaW1tYSkKZXhwcl9tYXQgPC0gbm9ybWFsaXplQmV0d2VlbkFycmF5cyhleHByX21hdCkKZXhwcl9tYXQgPC0gbG9nMihleHByX21hdCsxKSAj5L2/55SobG9nMiBzY2FsZQoKI1BDQQpsaWJyYXJ5KGdnZm9ydGlmeSkgCmRmIDwtIGFzLmRhdGEuZnJhbWUodChleHByX21hdCkpIApkZiRncm91cCA8LSBncm91cF9maWxlIAphdXRvcGxvdChwcmNvbXAoZGZbLDE6KG5jb2woZGYpLTEpXSksIGRhdGE9ZGYsIGNvbG91ciA9ICdncm91cCcpKyB0aGVtZV9idygpIAoKIyBJZiB0aGUgc2VxdWVuY2luZyBkZXB0aCBpcyByZWFzb25hYmx5IGNvbnNpc3RlbnQgYWNyb3NzIHRoZSBSTkEgc2FtcGxlcywgdGhlbiB0aGUgc2ltcGxlc3QgYW5kIG1vc3Qgcm9idXN0IGFwcHJvYWNoIHRvIGRpZmZlcmVudGlhbCBleGlzIHRvIHVzZSBsaW1tYS10cmVuZC4KCmZpdCA8LSBsbUZpdChleHByX21hdCwgZ3JvdXBfZmlsZSkKZml0IDwtIHRyZWF0KGZpdCwgbGZjPWxvZzIoMS4yKSwgdHJlbmQ9VFJVRSkKdG9wVHJlYXQoZml0LCBjb2VmPW5jb2woZGVzaWduKSkKCmBgYAoKCmBgYHtyfQpsaWJyYXJ5KGdncHVicikKZGF0IDwtIGV4cHJfbWF0CmRlc2lnbiA8LSBtb2RlbC5tYXRyaXgofmZhY3Rvcihncm91cF9maWxlKSkKZml0IDwtIGxtRml0KGRhdCwgZGVzaWduKQpmaXQgPC0gZUJheWVzKGZpdCkKIyBvcHRpb25zKGRpZ2l0cyA9IDQpCnRvcFRhYmxlKGZpdCxjb2VmPTIsYWRqdXN0PSdCSCcpCmRlZyA8LSB0b3BUYWJsZShmaXQsY29lZj0yLGFkanVzdD0nQkgnLG51bWJlciA9IEluZikKaGVhZChkZWcpIAoKd3JpdGUuY3N2KGRlZywiLi9kYXRhdGFibGUvc3RhYmxlIHZzIHVuc3RhYmxlLmNzdiIpCiMjIGxvb2sgdXAgRlJaQiwgU09TVCwgUFJETTYsIE9HTgpkczFtYXJrZXJzW2RzMW1hcmtlcnMkY2x1c3RlciA9PSAiU01DMiIsXSRnZW5lCgpkczJtYXJrZXJzW2RzMm1hcmtlcnMkY2x1c3RlciA9PSAiU01DMyIsXSRnZW5lCgpzbWMybWFya2VycyA8LSBpbnRlcnNlY3QoZHMxbWFya2Vyc1tkczFtYXJrZXJzJGNsdXN0ZXIgPT0gIlNNQzIiLF0kZ2VuZSwgZHMybWFya2Vyc1tkczJtYXJrZXJzJGNsdXN0ZXIgPT0gIlNNQzMiLF0kZ2VuZSkKCgpkZWdbaW50ZXJzZWN0KHNtYzJtYXJrZXJzLCByb3duYW1lcyhkZWcpKSxdCgpkczFtYXJrZXJzW2RzMW1hcmtlcnMkY2x1c3RlciA9PSAiU01DMSIsXSRnZW5lCgpkczJtYXJrZXJzW2RzMm1hcmtlcnMkY2x1c3RlciA9PSAiU01DMSIsXSRnZW5lCgpTTUMxbWFya2VycyA8LSBpbnRlcnNlY3QoZHMxbWFya2Vyc1tkczFtYXJrZXJzJGNsdXN0ZXIgPT0gIlNNQzEiLF0kZ2VuZSwgZHMybWFya2Vyc1tkczJtYXJrZXJzJGNsdXN0ZXIgPT0gIlNNQzEiLF0kZ2VuZSkKCmRlZ1tpbnRlcnNlY3QoU01DMW1hcmtlcnMsIHJvd25hbWVzKGRlZykpLF0KYGBgCgpgYGB7cn0KIyBsb2dGQ190aHJlc2hvbGQgPSAxCiMgcHZhbHVlX3RocmVzaG9sZCA9IDAuMDUKc2VsZWN0ZWRfZ2VuZXMgPSBhcy5jaGFyYWN0ZXIocmVhZC50YWJsZSgiU01DMiIpJFYxKQoKdm9sY2Fub19wbG90IDwtIGZ1bmN0aW9uKGZpbGVuYW1lLCBzZWxlY3RlZF9nZW5lcywgbG9nRkNfdGhyZXNob2xkID0gMSwgcHZhbHVlX3RocmVzaG9sZCA9IDAuMDUpCnsKICBmPC1yZWFkLmNzdigiLi9kYXRhdGFibGUvc3RhYmxlIHZzIHVuc3RhYmxlLmNzdiIpCiAgZiR0aHJlc2hvbGQgPC0gZmFjdG9yKGlmZWxzZShmJGFkai5QLlZhbCA8IHB2YWx1ZV90aHJlc2hvbGQgJiBhYnMoZiRsb2dGQykgPj0gbG9nRkNfdGhyZXNob2xkLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKGYkbG9nRkM+PSBsb2dGQ190aHJlc2hvbGQgLCdVcCcsJ0Rvd24nKSwnTi5TLicpLAogICAgICAgICAgICAgICAgICAgICAgIGxldmVscz1jKCdVcCcsJ0Rvd24nLCdOLlMuJykpCiAgCiAgIGdncGxvdChmLGFlcyh4PWxvZ0ZDLHk9LWxvZzEwKGFkai5QLlZhbCksY29sb3I9dGhyZXNob2xkKSkrCiAgICBnZW9tX3BvaW50KCkrCiAgICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzPWMoIiNDQzAwMDAiLCIjMmY1Njg4IiwiI0JCQkJCQiIpKSsKICAgIGdlb21fdGV4dF9yZXBlbCgKICAgICAgZGF0YSA9IGZbZiRYICVpbiUgc2VsZWN0ZWRfZ2VuZXMsXSwKICAgICAgYWVzKGxhYmVsID0gWCksCiAgICAgIHNpemUgPSA1LCBtYXgub3ZlcmxhcHMgPSAxMDAwLAogICAgICBjb2w9ImJsYWNrIiwgc2VnbWVudC5jb2xvciA9ICJibGFjayIsIHNob3cubGVnZW5kID0gRkFMU0UgKSsKICAgIHRoZW1lKHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2JsYW5rKCksIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgICBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLCBheGlzLmxpbmUgPSBlbGVtZW50X2xpbmUoY29sb3VyID0gImJsYWNrIikpKwogICAgdGhlbWUoCiAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMjApLCBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTUpLAogICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDIwKSwgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE1KSwgCiAgICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAyMCksIAogICAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCkKICAgICkrCiAgICB5bGFiKCctbG9nMTAgKHAtYWRqKScpICsKICAgIHhsYWIoJ2xvZzIgKEZvbGRDaGFuZ2UpJykgKwogICAgZ2VvbV92bGluZSh4aW50ZXJjZXB0PWMoLWxvZ0ZDX3RocmVzaG9sZCxsb2dGQ190aHJlc2hvbGQpLCBsdHk9Myxjb2w9ImJsYWNrIixsd2Q9MC41KSArCiAgICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPWMoMCwtbG9nMTAocHZhbHVlX3RocmVzaG9sZCkpLGx0eT0zLGNvbD0iYmxhY2siLGx3ZD0wLjUpCn0KCnNlbGVjdGVkX2dlbmVzIDwtIGMoYXMuY2hhcmFjdGVyKHJlYWQudGFibGUoIlNNQzIiKSRWMSkpCgpwIDwtIHZvbGNhbm9fcGxvdCgiLi9kYXRhdGFibGUvc3RhYmxlIHZzIHVuc3RhYmxlLmNzdiIsc2VsZWN0ZWRfZ2VuZXMpICsgZ2d0aXRsZSgic3RhYmxlIHZzIHVuc3RhYmxlLCBTTUMyIG1hcmtlciIpCgpnZ3NhdmUoIlNNQzJfc3RhYmxlIHZzIHVuc3RhYmxlLnBuZyIscGxvdCA9IHAsZGV2aWNlID0gcG5nLGhlaWdodCA9IDQsIHdpZHRoID0gNikKYGBgCgoKQWRkIGEgbmV3IGNodW5rIGJ5IGNsaWNraW5nIHRoZSAqSW5zZXJ0IENodW5rKiBidXR0b24gb24gdGhlIHRvb2xiYXIgb3IgYnkgcHJlc3NpbmcgKkN0cmwrQWx0K0kqLgoKV2hlbiB5b3Ugc2F2ZSB0aGUgbm90ZWJvb2ssIGFuIEhUTUwgZmlsZSBjb250YWluaW5nIHRoZSBjb2RlIGFuZCBvdXRwdXQgd2lsbCBiZSBzYXZlZCBhbG9uZ3NpZGUgaXQgKGNsaWNrIHRoZSAqUHJldmlldyogYnV0dG9uIG9yIHByZXNzICpDdHJsK1NoaWZ0K0sqIHRvIHByZXZpZXcgdGhlIEhUTUwgZmlsZSkuCgpUaGUgcHJldmlldyBzaG93cyB5b3UgYSByZW5kZXJlZCBIVE1MIGNvcHkgb2YgdGhlIGNvbnRlbnRzIG9mIHRoZSBlZGl0b3IuIENvbnNlcXVlbnRseSwgdW5saWtlICpLbml0KiwgKlByZXZpZXcqIGRvZXMgbm90IHJ1biBhbnkgUiBjb2RlIGNodW5rcy4gSW5zdGVhZCwgdGhlIG91dHB1dCBvZiB0aGUgY2h1bmsgd2hlbiBpdCB3YXMgbGFzdCBydW4gaW4gdGhlIGVkaXRvciBpcyBkaXNwbGF5ZWQuCg==